package com.fanrui.code.configfile;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.ibatis.javassist.Modifier;
import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;

import com.fanrui.code.common.annotation.ConfigFile;
import com.fanrui.code.db.jvmdb.IPersistable;

public abstract class LoadConfigFile<ID_TYPE, CONFIG_ENTITY extends IPersistable<ID_TYPE>> {
	
	protected Map<String, Map<ID_TYPE,CONFIG_ENTITY>> configFiles = new HashMap<String, Map<ID_TYPE,CONFIG_ENTITY>>();
	
	private final String packageName;

	protected LoadConfigFile(String packageName) {
		super();
		this.packageName = packageName;
		registe();
	}
	
	/**
	 *  扫描某个包下面所有的带有{@link ConfigFile}注释的类，
	 *  然后加载到内存中
	 *  
	 */
	public void registe() {
		// 找到packageName包下面的所有类
		Reflections reflections = new Reflections(packageName, new SubTypesScanner(false));
		Set<String> allClasses = reflections.getAllTypes();
		for(String className : allClasses) {
			Class<?> clazz = ReflectionUtils.forName(className);
			if(clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()) || !clazz.isAnnotationPresent(ConfigFile.class)) {
				continue;
			}
			Map<ID_TYPE,CONFIG_ENTITY> configfiles = loadConfigFile(className);
			if(configfiles == null){
				configfiles = Collections.emptyMap();
			}
			this.configFiles.put(clazz.getSimpleName(), configfiles);
		}
	}
	
	@SuppressWarnings("unchecked")
	public <T> T getConfigFileById(Class<T> clazz, ID_TYPE id) {
		Map<ID_TYPE,CONFIG_ENTITY> configFiles = this.configFiles.get(clazz.getSimpleName());
		if(configFiles != null){
			return (T) configFiles.get(id);
		}else{
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public <T> Map<ID_TYPE,T> getConfigFilesByName(Class<T> c){
		Map<ID_TYPE,CONFIG_ENTITY> configFiles = this.configFiles.get(c.getSimpleName());
		return (Map<ID_TYPE, T>) configFiles;
	}
	
	protected abstract Map<ID_TYPE,CONFIG_ENTITY> loadConfigFile(String configFileName);

}
